package com.ls.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ls.server.domain.ChatMessage;
import com.ls.server.domain.ChatSession;
import com.ls.server.dto.ChatMessageDTO;
import com.ls.server.dto.ChatQueryDTO;
import com.ls.server.mapper.ChatMessageMapper;
import com.ls.server.service.ChatAttachmentService;
import com.ls.server.service.ChatMessageService;
import com.ls.server.service.ChatService;
import com.ls.server.service.ChatSessionService;
import com.ls.server.vo.ChatAttachmentVO;
import com.ls.server.vo.ChatMessageVO;
import com.ls.server.vo.PageResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 聊天消息Service实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChatMessageServiceImpl extends ServiceImpl<ChatMessageMapper, ChatMessage> implements ChatMessageService {

    private final ChatSessionService sessionService;
    private final ChatAttachmentService attachmentService;
    private final ChatService chatService;

    @Override
    public List<ChatMessageVO> listSessionMessages(String sessionId) {
        LambdaQueryWrapper<ChatMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatMessage::getSessionId, sessionId)
               .orderByAsc(ChatMessage::getCreateTime);

        List<ChatMessage> messages = baseMapper.selectList(wrapper);
        return convertToVoList(messages);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long sendMessage(ChatMessageDTO dto) {
        // 保存消息
        ChatMessage message = new ChatMessage();
        BeanUtils.copyProperties(dto, message);
        message.setCreateTime(LocalDateTime.now());

        // 如果消息类型为空，则默认设置为用户消息
        if (message.getMessageType() == null) {
            message.setMessageType("user");
        }

        baseMapper.insert(message);

        // 更新会话最后一条消息
        if (StringUtils.hasText(dto.getContent())) {
            sessionService.updateLastMessage(dto.getSessionId(), dto.getContent());
        }

        // 关联附件
        if (dto.getAttachmentIds() != null && !dto.getAttachmentIds().isEmpty()) {
            attachmentService.linkAttachmentsToMessage(message.getId(), dto.getAttachmentIds());
        }

        // 如果是用户消息，调用AI生成回复(可选)
        if ("user".equals(dto.getMessageType())) {
            // 这里可以调用AI服务生成回复
            String aiResponse = getAiResponse(dto.getSessionId(), dto.getContent(), dto.getModelId());

            if (StringUtils.hasText(aiResponse)) {
                // 保存AI回复消息
                ChatMessage aiMessage = new ChatMessage();
                aiMessage.setSessionId(dto.getSessionId());
                aiMessage.setMessageType("assistant");
                aiMessage.setContent(aiResponse);
                aiMessage.setUserId(dto.getUserId());
                aiMessage.setModelId(dto.getModelId());
                aiMessage.setCreateTime(LocalDateTime.now());

                baseMapper.insert(aiMessage);

                // 更新会话最后一条消息为AI回复
                sessionService.updateLastMessage(dto.getSessionId(), aiResponse);
            }
        }

        return message.getId();
    }

    @Override
    public List<ChatMessageVO> listRecentUserMessages(Long userId, Integer limit) {
        LambdaQueryWrapper<ChatMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatMessage::getUserId, userId)
               .eq(ChatMessage::getMessageType, "user")
               .orderByDesc(ChatMessage::getCreateTime)
               .last("LIMIT " + limit);

        List<ChatMessage> messages = baseMapper.selectList(wrapper);
        return convertToVoList(messages);
    }

    @Override
    public PageResult<ChatMessageVO> page(ChatQueryDTO queryDTO) {
        Page<ChatMessage> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        LambdaQueryWrapper<ChatMessage> wrapper = new LambdaQueryWrapper<>();

        // 添加查询条件
        if (StringUtils.hasText(queryDTO.getSessionId())) {
            wrapper.eq(ChatMessage::getSessionId, queryDTO.getSessionId());
        }

        if (queryDTO.getUserId() != null) {
            wrapper.eq(ChatMessage::getUserId, queryDTO.getUserId());
        }

        if (StringUtils.hasText(queryDTO.getKeyword())) {
            wrapper.like(ChatMessage::getContent, queryDTO.getKeyword());
        }

        // 排序
        wrapper.orderByDesc(ChatMessage::getCreateTime);

        IPage<ChatMessage> result = baseMapper.selectPage(page, wrapper);
        List<ChatMessageVO> voList = convertToVoList(result.getRecords());

        return new PageResult<>(voList, result.getTotal());
    }

    @Override
    public String getAiResponse(String sessionId, String prompt, Long modelId) {
        // 这里可以调用第三方AI服务，如OpenAI等
        // 这里只是简单示例，实际应根据modelId调用不同的AI服务
        log.info("调用AI服务生成回复，sessionId={}, modelId={}", sessionId, modelId);
        // 直接返回回答内容，不添加前缀
        return chatService.chat(modelId, prompt, null);
    }

    /**
     * 将实体转换为VO
     */
    private ChatMessageVO convertToVo(ChatMessage message) {
        ChatMessageVO vo = new ChatMessageVO();
        BeanUtils.copyProperties(message, vo);

        // 获取附件列表
        List<ChatAttachmentVO> attachments = attachmentService.listByMessageId(message.getId());
        vo.setAttachments(attachments);

        return vo;
    }

    /**
     * 将实体列表转换为VO列表
     */
    private List<ChatMessageVO> convertToVoList(List<ChatMessage> messages) {
        if (messages == null || messages.isEmpty()) {
            return new ArrayList<>();
        }
        return messages.stream()
                .map(this::convertToVo)
                .collect(Collectors.toList());
    }
}
